﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Schism.libs;
using Schism.Core;

namespace Schism.Mapping
{
    [Serializable]
    public class CellMap : MapBase<CellBase>
    {
        //Fields        
        [NonSerialized]
        public RenderTarget2D MapRenderBuffer;
       
        //ctor
        public CellMap(CellBase[,] matrix)
            : base(matrix)
        {
            
        }

        //Methods
        public void CreateMapRenderBuffer()
        {
            MapRenderBuffer = new RenderTarget2D(ObjectHolder.GameObject.GraphicsDevice,
                (int)ObjectHolder.GameCamera.CameraViewport.X, (int)ObjectHolder.GameCamera.CameraViewport.Y,
                false, SurfaceFormat.Color, DepthFormat.None);

            using (SpriteBatch mapBatch = new SpriteBatch(MapRenderBuffer.GraphicsDevice))
            {
                mapBatch.GraphicsDevice.SetRenderTarget(MapRenderBuffer);
                mapBatch.GraphicsDevice.Clear(Color.White);
                mapBatch.Begin();

                foreach (CellBase cell in FilterByVisible())
                    cell.Render(mapBatch, null);

                mapBatch.End();
                mapBatch.GraphicsDevice.SetRenderTarget(null);
            }
        }
        
        //Mutators
        public IEnumerable<CellBase> ToList()
        {
            for (int y = 0; y < MapHeight; y++)
                for (int x = 0; x < MapWidth; x++)
                    yield return this[x, y];
        }
        public IEnumerable<CellBase> FilterBy(Func<CellBase, bool> func)
        {
            return this.ToList().Where(func);
        }
        public IEnumerable<CellBase> FilterByVisible()
        {
            //Calculate the Minimum tiles shown
            int minX, minY;
            minX = (int)(ObjectHolder.GameCamera.CameraTopLeft.X / Globals.GLOBAL_TILE_WIDTH);
            minY = (int)(ObjectHolder.GameCamera.CameraTopLeft.Y / Globals.GLOBAL_TILE_HEIGHT);
            minX = minX >= 1 ? minX - 1 : 0;
            minY = minY >= 1 ? minY - 1 : 0;

            //Calculate the Maximum Tiles shown
            int maxX, maxY;
            maxX = (int)((ObjectHolder.GameCamera.CameraTopLeft.X + ObjectHolder.GameCamera.CameraViewport.X) / Globals.GLOBAL_TILE_WIDTH);
            maxY = (int)((ObjectHolder.GameCamera.CameraTopLeft.Y + ObjectHolder.GameCamera.CameraViewport.Y) / Globals.GLOBAL_TILE_HEIGHT);
            maxX = maxX < MapWidth ? maxX + 1 : MapWidth;
            maxY = maxY < MapWidth ? maxY + 1 : MapHeight;

            for (int y = minY; y < maxY; y++)
                for (int x = minX; x < maxX; x++)
                    yield return this[x, y];
        }

        public void Mine(int x, int y)
        {
            this[x, y].Mine();
        }
    }
}
